<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>Snapping &amp; Splitting</title>
    <link rel="stylesheet" href="../theme/default/style.css" type="text/css">
    <!--[if lte IE 6]>
        <link rel="stylesheet" href="../theme/default/ie6-style.css" type="text/css" />
    <![endif]-->
    <link rel="stylesheet" href="style.css" type="text/css">
    <style type="text/css">
        .olControlEditingToolbar .olControlModifyFeatureItemInactive { 
            background-position: -1px -1px;
        }
        .olControlEditingToolbar .olControlModifyFeatureItemActive { 
            background-position: -1px -24px;
        }
        label.head {
            font-weight: bold;
            padding: 1em 0 0.1em 0;
            border-bottom: 1px solid gray;
        }
        td {
            padding: 0.25em 1em;
        }
        tr.head td {
            text-align: center;
            font-weight: bold;
        }
    </style>
    <script src="../lib/Firebug/firebug.js"></script>
    <script src="../lib/OpenLayers.js"></script>
    <script type="text/javascript">

        OpenLayers.Feature.Vector.style['default']['strokeWidth'] = '2';

        function init() {
            initMap();
            initUI();
        }


        var map, draw, modify, snap, split, vectors;
        function initMap() {

            map = new OpenLayers.Map('map');
            var styles = new OpenLayers.StyleMap({
                "default": new OpenLayers.Style(null, {
                    rules: [
                        new OpenLayers.Rule({
                            symbolizer: {
                                "Point": {
                                    pointRadius: 5,
                                    graphicName: "square",
                                    fillColor: "white",
                                    fillOpacity: 0.25,
                                    strokeWidth: 1,
                                    strokeOpacity: 1,
                                    strokeColor: "#333333"
                                },
                                "Line": {
                                    strokeWidth: 3,
                                    strokeOpacity: 1,
                                    strokeColor: "#666666"
                                }
                            }
                        })
                    ]
                }),
                "select": new OpenLayers.Style({
                    strokeColor: "#00ccff",
                    strokeWidth: 4
                }),
                "temporary": new OpenLayers.Style(null, {
                    rules: [
                        new OpenLayers.Rule({
                            symbolizer: {
                                "Point": {
                                    pointRadius: 5,
                                    graphicName: "square",
                                    fillColor: "white",
                                    fillOpacity: 0.25,
                                    strokeWidth: 1,
                                    strokeOpacity: 1,
                                    strokeColor: "#333333"
                                },
                                "Line": {
                                    strokeWidth: 3,
                                    strokeOpacity: 1,
                                    strokeColor: "#00ccff"
                                }
                            }
                        })
                    ]
                })
            });

            // allow testing of specific renderers via "?renderer=Canvas", etc
            var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
            renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;

            // create three vector layers
            vectors = new OpenLayers.Layer.Vector("Lines", {
                isBaseLayer: true,
                strategies: [new OpenLayers.Strategy.Fixed()],                
                protocol: new OpenLayers.Protocol.HTTP({
                    url: "data/roads.json",
                    format: new OpenLayers.Format.GeoJSON()
                }),
                styleMap: styles,
                maxExtent: new OpenLayers.Bounds(
                    1549471.9221, 6403610.94, 1550001.32545, 6404015.8
                ),
                renderers: renderer
            });
            map.addLayer(vectors);
            
            // configure the snapping agent
            snap = new OpenLayers.Control.Snapping({layer: vectors});
            map.addControl(snap);
            snap.activate();
            
            // configure split agent
            split = new OpenLayers.Control.Split({
                layer: vectors,
                source: vectors,
                tolerance: 0.0001,
                eventListeners: {
                    aftersplit: function(event) {
                        flashFeatures(event.features);
                    }
                }
            });
            map.addControl(split);
            split.activate();

            // add some editing tools to a panel
            var panel = new OpenLayers.Control.Panel({
                displayClass: "olControlEditingToolbar"
            });
            draw = new OpenLayers.Control.DrawFeature(
                vectors, OpenLayers.Handler.Path,
                {displayClass: "olControlDrawFeaturePoint", title: "Draw Features"}
            );
            modify = new OpenLayers.Control.ModifyFeature(
                vectors, {displayClass: "olControlModifyFeature", title: "Modify Features"}
            );
            panel.addControls([
                new OpenLayers.Control.Navigation({title: "Navigate"}),
                draw, modify
            ]);
            map.addControl(panel);
            
            map.addControl(new OpenLayers.Control.MousePosition());
            
            map.zoomToMaxExtent();
        }

        function flashFeatures(features, index) {
            if(!index) {
                index = 0;
            }
            var current = features[index];
            if(current && current.layer === vectors) {
                vectors.drawFeature(features[index], "select");
            }
            var prev = features[index-1];
            if(prev && prev.layer === vectors) {
                vectors.drawFeature(prev, "default");
            }
            ++index;
            if(index <= features.length) {
                window.setTimeout(function() {flashFeatures(features, index)}, 75);
            }
        }

        /**
         * Add behavior to page elements.  This basically lets us set snapping
         * target properties with the checkboxes and text inputs.  The checkboxes
         * toggle the target node, vertex, or edge (boolean) values.  The
         * text inputs set the nodeTolerance, vertexTolerance, or edgeTolerance
         * property values.
         */
        function initUI() {
            // add behavior to snap elements
            var snapCheck = $("snap_toggle");
            snapCheck.checked = true;
            snapCheck.onclick = function() {
                if(snapCheck.checked) {
                    snap.activate();
                    $("snap_options").style.display = "block";
                } else {
                    snap.deactivate();
                    $("snap_options").style.display = "none";
                }
            };
            var target, type, tog, tol;
            var types = ["node", "vertex", "edge"];
            var target = snap.targets[0];
            for(var j=0; j<types.length; ++j) {
                type = types[j];
                tog = $("target_" + type);
                tog.checked = target[type];
                tog.onclick = (function(tog, type, target) {
                    return function() {target[type] = tog.checked;}
                })(tog, type, target);
                tol = $("target_" + type + "Tolerance");
                tol.value = target[type + "Tolerance"];
                tol.onchange = (function(tol, type, target) {
                    return function() {
                        target[type + "Tolerance"] = Number(tol.value) || 0;
                    }
                })(tol, type, target);
            }

            // add behavior to split elements
            var splitCheck = $("split_toggle");
            splitCheck.checked = true;
            splitCheck.onclick = function() {
                if(splitCheck.checked) {
                    split.activate();
                    $("split_options").style.display = "block";
                } else {
                    split.deactivate();
                    $("split_options").style.display = "none";
                }
            };
            var edgeCheck = $("edge_toggle");
            edgeCheck.checked = split.edge;
            edgeCheck.onclick = function() {
                split.edge = edgeCheck.checked;
            };
            
            $("clear").onclick = function() {
                modify.deactivate();
                vectors.destroyFeatures();
            };
            
        }
    
    </script>
  </head>
  <body onload="init()">
    <h1 id="title">Snapping & Splitting Example</h1>
    <div id="tags">
        vector, feature, splitting, snapping, stylemap, advanced
    </div>    
    <div id="shortdesc">A demonstration snapping and splitting while editing vector features.</div>
    <div id="map" class="smallmap"></div>
    <br>
    <input type="checkbox" id="snap_toggle" />
    <label for="snap_toggle" class="head">Enable Snapping</label>
    <table id="snap_options">
        <tbody>
            <tr class="head">
                <td>target</td><td>node</td><td>vertex</td><td>edge</td>
            </tr>
            <tr>
                <td>roads</td>
                <td><input type="checkbox" id="target_node" /><input id="target_nodeTolerance" type="text" size="3" /></td>
                <td><input type="checkbox" id="target_vertex" /><input id="target_vertexTolerance" type="text" size="3" /></td>
                <td><input type="checkbox" id="target_edge" /><input id="target_edgeTolerance" type="text" size="3" /></td>
            </tr>
        </tbody>
    </table>
    <br>
    <input type="checkbox" id="split_toggle" />
    <label for="split_toggle" class="head">Enable Splitting</label>
    <table id="split_options">
        <tbody>
            <tr>
                <td><label for="edge_toggle">edges split</label></td>
                <td><input type="checkbox" id="edge_toggle" /></td>
            </tr>
        </tbody>
    </table>
    <br>
    <button id="clear">clear</button> Clear all features.
  </body>
</html>
